"""
病历 JSON 解析器
用于解析病历 JSON 数据并提取关键字段
"""
from typing import Dict, Any, Optional, List
from datetime import datetime
from app.core.logger import app_logger
import re


class MedicalRecordParser:
    """病历 JSON 解析器"""
    
    @staticmethod
    def parse_date(date_str: Optional[str]) -> Optional[datetime]:
        """
        解析日期字符串
        支持格式：2025-03-11 20:04, 2025-03-11, 2025/03/11
        """
        if not date_str:
            return None
        
        try:
            # 移除多余空格
            date_str = date_str.strip()
            
            # 尝试多种日期格式
            formats = [
                "%Y-%m-%d %H:%M",
                "%Y-%m-%d",
                "%Y/%m/%d %H:%M",
                "%Y/%m/%d",
                "%Y年%m月%d日",
            ]
            
            for fmt in formats:
                try:
                    return datetime.strptime(date_str, fmt)
                except ValueError:
                    continue
            
            app_logger.warning(f"无法解析日期: {date_str}")
            return None
        except Exception as e:
            app_logger.error(f"日期解析错误: {e}")
            return None
    
    @staticmethod
    def parse_age(age_str: Optional[str]) -> Optional[int]:
        """
        解析年龄字符串
        示例：25岁 -> 25, 3月 -> 0
        """
        if not age_str:
            return None
        
        try:
            # 提取数字
            numbers = re.findall(r'\d+', str(age_str))
            if numbers:
                age = int(numbers[0])
                # 如果包含"月"，则年龄为0
                if '月' in str(age_str):
                    return 0
                return age
            return None
        except Exception as e:
            app_logger.error(f"年龄解析错误: {e}")
            return None
    
    @staticmethod
    def parse_diagnosis(diagnosis_str: Optional[str]) -> List[str]:
        """
        解析诊断字符串
        示例：1.痛风性关节炎 2.胃炎? -> ["痛风性关节炎", "胃炎?"]
        """
        if not diagnosis_str:
            return []
        
        try:
            # 按数字编号分割
            diagnoses = re.split(r'\d+\.', diagnosis_str)
            # 过滤空字符串并去除空格
            diagnoses = [d.strip() for d in diagnoses if d.strip()]
            return diagnoses
        except Exception as e:
            app_logger.error(f"诊断解析错误: {e}")
            return []
    
    @staticmethod
    def parse_medications(medications_data: Optional[List[Dict[str, Any]]]) -> List[Dict[str, Any]]:
        """
        解析用药信息
        """
        if not medications_data:
            return []
        
        parsed_meds = []
        for med in medications_data:
            try:
                # 提取剂量数值和单位
                dosage_value = None
                dosage_unit = None
                if '剂量' in med:
                    dosage_str = str(med['剂量'])
                    # 提取数字
                    numbers = re.findall(r'\d+\.?\d*', dosage_str)
                    if numbers:
                        dosage_value = float(numbers[0])
                    # 提取单位
                    units = re.findall(r'[a-zA-Z]+|mg|g|ml|片|粒|袋|支', dosage_str)
                    if units:
                        dosage_unit = units[-1]
                
                # 提取天数
                duration = None
                if '天数' in med:
                    duration_str = str(med['天数'])
                    numbers = re.findall(r'\d+', duration_str)
                    if numbers:
                        duration = int(numbers[0])
                
                parsed_meds.append({
                    'medication_name': med.get('名称', ''),
                    'specification': med.get('规格'),
                    'route': med.get('用法'),
                    'dosage_value': int(dosage_value) if dosage_value else None,
                    'dosage_unit': dosage_unit,
                    'duration': duration,
                    'total_quantity': med.get('总量'),
                    'raw_medication_data': med
                })
            except Exception as e:
                app_logger.error(f"用药解析错误: {e}, 数据: {med}")
                continue
        
        return parsed_meds
    
    @staticmethod
    def parse_instructions(instructions_data: Optional[List[str]]) -> List[Dict[str, str]]:
        """
        解析医嘱信息
        """
        if not instructions_data:
            return []
        
        return [
            {'instruction_text': instruction.strip()}
            for instruction in instructions_data
            if instruction.strip()
        ]
    
    @classmethod
    def parse(cls, raw_data: Dict[str, Any]) -> Dict[str, Any]:
        """
        解析完整的病历 JSON 数据
        
        Args:
            raw_data: 原始 JSON 数据
            
        Returns:
            解析后的结构化数据
        """
        try:
            # 提取患者信息
            patient_info = raw_data.get('患者信息', {})
            condition_info = raw_data.get('病情信息', {})
            doctor_info = raw_data.get('医生信息', {})
            
            # 构建结构化数据
            parsed_data = {
                # 患者基本信息
                'patient_name': patient_info.get('姓名', '未知'),
                'patient_age': cls.parse_age(patient_info.get('年龄')),
                'patient_gender': patient_info.get('性别'),
                'patient_card_number': patient_info.get('就诊卡号'),
                'department': patient_info.get('科别'),
                'visit_date': cls.parse_date(patient_info.get('就诊日期')),
                
                # 病情信息
                'chief_complaint': condition_info.get('主诉'),
                'present_illness': condition_info.get('现病史'),
                'allergy_history': condition_info.get('过敏史'),
                'past_history': condition_info.get('既往史'),
                'personal_history': condition_info.get('个人史'),
                'menstrual_history': condition_info.get('月经史'),
                'physical_exam': condition_info.get('体格检查'),
                'auxiliary_exam': condition_info.get('辅助检查'),
                'diagnosis': cls.parse_diagnosis(condition_info.get('诊断')),
                
                # 医生信息
                'doctor_name': doctor_info.get('医生签名'),
                
                # 原始数据
                'raw_data': raw_data,
                
                # 用药和医嘱信息（用于后续创建关联记录）
                '_medications': cls.parse_medications(raw_data.get('用药信息', [])),
                '_instructions': cls.parse_instructions(raw_data.get('嘱托与注意事项', []))
            }
            
            app_logger.info(f"成功解析病历: {parsed_data['patient_name']}")
            return parsed_data
            
        except Exception as e:
            app_logger.error(f"病历解析失败: {e}", exc_info=True)
            raise ValueError(f"病历数据解析失败: {str(e)}")
    
    @classmethod
    def validate(cls, raw_data: Dict[str, Any]) -> tuple[bool, List[str]]:
        """
        验证病历数据的基本完整性
        
        Returns:
            (是否有效, 错误信息列表)
        """
        errors = []
        
        # 检查必需字段
        if '患者信息' not in raw_data:
            errors.append("缺少 '患者信息' 字段")
        else:
            patient_info = raw_data['患者信息']
            if '姓名' not in patient_info or not patient_info['姓名']:
                errors.append("缺少患者姓名")
        
        if '病情信息' not in raw_data:
            errors.append("缺少 '病情信息' 字段")
        
        return len(errors) == 0, errors

